using Aurora.TaskScheduler.Abstractions;
using Aurora.TaskScheduler.Abstractions.Attributes;
using Aurora.TaskScheduler.Abstractions.BaseModel;
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using Aurora.TaskScheduler.Extension.Extensions;
using Aurora.TaskScheduler.Abstractions.Message;
using Aurora.TaskScheduler.Abstractions.Storage;
using Aurora.TaskScheduler.Extension.Internel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;

namespace Aurora.TaskScheduler.Extension.BaseJobs;

/// <summary>
/// http job 
/// </summary>
public class HttpResultJob : IJob
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ILogger<HttpResultJob> _logger;
    private readonly IDataStorage _storage;
    private readonly ITaskHandler _taskHandler;
    private readonly TaskSchedulerOptions _options;
    private readonly IServiceScopeFactory _serviceProvider;

    public HttpResultJob(ILogger<HttpResultJob> logger, IDataStorage storage,
        IHttpClientFactory httpClientFactory, ITaskHandler taskHandler, IOptions<TaskSchedulerOptions> options,
        IServiceScopeFactory serviceProvider)
    {
        _logger = logger;
        _storage = storage;
        _httpClientFactory = httpClientFactory;
        _taskHandler = taskHandler;
        _serviceProvider = serviceProvider;
        _options = options.Value;
    }

    /// <summary>
    /// 执行
    /// </summary>
    /// <param name="context"></param>
    public async Task Execute(IJobExecutionContext context)
    {
        DateTime dateTime = DateTime.Now;
        AbstractTrigger trigger = (context as JobExecutionContextImpl).Trigger as AbstractTrigger;
        AppTask task = await _storage.GetTaskByName(trigger.JobName, trigger.JobGroup);

        //估计是为了异步等待吧
        if (task == null)
        {
            task = await _storage.GetTaskByName(trigger.JobName, trigger.JobGroup);
        }

        if (task == null)
        {
            _logger.LogError($"组别:{trigger.Group},名称:{trigger.Name},的作业未找到,可能已被移除");
            return;
        }

        _logger.LogTrace(
            $"组别:{trigger.Group},名称:{trigger.Name},的作业开始执行,时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss")}");
        var appTaskLog = new AppTaskLog()
        {
            Id = Guid.NewGuid().ToString(),
            TaskId = task.Id,
            TaskName = task.TaskName,
            GroupName = task.GroupName,
            BeginDate = dateTime,
        };
        if (string.IsNullOrEmpty(task.ApiUrl) || task.ApiUrl == "/")
        {
            _logger.LogError(
                $"组别:{trigger.Group},名称:{trigger.Name},参数非法或者异常!,时间:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:sss")}");
            return;
        }

        var executeResult = await ExecuteAsync(task);

        appTaskLog.EndDate = DateTime.Now;
        appTaskLog.CreateTime = DateTime.Now;
        appTaskLog.ElapsedMilliseconds =
            (long)(appTaskLog.EndDate.Value - appTaskLog.BeginDate.Value).TotalMilliseconds;
        appTaskLog.Success = executeResult.success;
        appTaskLog.Msg = executeResult.message;
        await _storage.AddLog(appTaskLog);

        task.LastRunTime = DateTime.Now;
        await _storage.Update(task);
        if (task.TaskExecuteType.Equals("ONE"))
        {
            // 需要进行删除任务
            await _taskHandler.Remove(task);
        }
    }


    /// <summary>
    /// 执行方法
    /// </summary>
    /// <param name="task"></param>
    /// <returns></returns>
    private async Task<(bool success, string message)> ExecuteAsync(AppTask task)
    {
        ITaskDistributeLock taskLockService = null;
        bool useTaskLock = false;
        string message;
        bool success = true;
        var scope = _serviceProvider.CreateScope();
        // 判断是否要使用分布式锁
        if (_options.UseTaskLock)
        {
            taskLockService = scope.ServiceProvider.GetService<ITaskDistributeLock>();
            if (taskLockService != null)
            {
              
                var lockResult = await taskLockService.TryLockAsync(task.Id, TimeSpan.FromMinutes(10));
                if (!lockResult)
                {
                    message = "获取分布式锁失败，判断另一个相同的任务实例正在执行！任务id：" + task.Id;
                    success = false;
                    return (success, message);
                }
                else
                {
                    useTaskLock = true;
                }
            }
        }

        Dictionary<string, string> header = new Dictionary<string, string>();
        if (!string.IsNullOrEmpty(task.ApiAuthKey)
            && !string.IsNullOrEmpty(task.ApiAuthValue))
        {
            header.Add(task.ApiAuthKey.Trim(), task.ApiAuthValue.Trim());
        }

        try
        {
            message = await _httpClientFactory.SendAsync(
                task.ApiRequestType.ToLower() == "get" ? HttpMethod.Get : HttpMethod.Post,
                task.ApiUrl,
                header);
        }
        catch (Exception e)
        {
            success = false;
            message = e.Message;
        }
        finally
        {
            // 判断是否要使用分布式锁
            if (taskLockService != null && useTaskLock)
            {
                await taskLockService.TryUnlockAsync(task.Id);
            }
        }

        return (success, message);
    }
}